<?php

namespace pmvc\data\sql\mysql;

use pmvc\data\sql\AbstractDataSource;
use pmvc\util\StringUtil;
use Exception;

class MysqlDataSource 
	extends AbstractDataSource {

	public $port;
	public $clientFlags;
	public $host;
	public $username;
	public $password;
	public $database;
	
	private $link = FALSE;

	public function createTransaction() {
		return new MysqlTransaction($this);
	}

	public function connect() {
		if ($this->link!==FALSE) {
			return;
		}
		if (empty($this->port)) {
			$this->port = "3306";
		}
		if (empty($this->clientFlags)) {
			$this->clientFlags = 0;
		}
		$this->link = mysql_connect(
			$this->host.":".$this->port,
			$this->username,
			$this->password,
			TRUE,
			$this->clientFlags);
		$this->assert($this->link!==false, "Connection failed");
		
		$db = mysql_select_db($this->database, $this->link);
		$this->assert($db!==false, "Selecting database failed");
	}
	
	public function escape($str) {
		return mysql_real_escape_string($str, $this->link);
	}
	
	public function query() {
		$a		= func_get_args();
        $sql 	= array_shift($a);
        $sql 	= $this->buildQuery($sql, $a);
        \pmvc\log\Log::trace(__CLASS__, "Executing query: {0}", $sql);
        $ret = mysql_query($sql, $this->link);
        $this->assert($ret!==false, "Query failed");
        return $ret;
	}
	
	public function update() {
		return call_user_func_array(array($this,"query"), func_get_args());
	}
	
	public function lastInsertId() {
		$ret = mysql_insert_id($this->link);
		$this->assert($ret!==false, "Getting insert id failed");
        return $ret;
	}
	
	public function numberOfRows($res) {
		$ret = mysql_num_rows($res);
		$this->assert($ret!==false, "Getting number of rows failed");
        return $ret;
	}
	
	public function fetchRowObject($res) {
		return mysql_fetch_object($res);
	}
	
	public function numberOfAffectedRows($res) {
		return mysql_affected_rows($this->link);
	}
	
	public function freeResult($res) {
		$ret = mysql_free_result($res);
		$this->assert($ret!==false, "Freeing result failed");
        return $ret;
	}

	public function getLastError() {
		return "errno ".mysql_errno($this->link)." - ".mysql_error($this->link);
	}

	private function assert($value, $message="") {
		if ($value!==true) {
			throw $this->createExceptionFromLastError($message);
		}
	}

	private function createExceptionFromLastError($message="", $previous=null) {
		return new Exception(
			$message." - ".mysql_error($this->link),
			mysql_errno($this->link),
			$previous);
	}

}

?>